<?php
/**
 * Created by PhpStorm.
 * User: dell
 * Date: 2019/8/14
 * Time: 14:45
 */
namespace Modules\Logic;
use App\Lib\OilcardException;
use App\Lib\Sms;
use App\Models\User;
use App\Models\UserLoginLog;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Redis;

class UserLogic extends BasicLogic
{
    /**
     * 密码登录
     * @param $mobile
     * @param $password
     * @param $openid
     * @param $unionid
     * @return string
     * @throws OilcardException
     */
    public function passwordLoginApp($mobile,$password,$openid,$unionid)
    {
        $user = (new User())->where("mobile",$mobile)->first();
        if (!$user){
            throw new OilcardException("手机号未注册");
        }
        if ($user->password!=$password){
            throw new OilcardException("密码错误");
        }
        if (empty($user->openid) && empty($user->unionid) && (!empty($openid) || !empty($unionid))) {
            $res = $this->bindWechat($user->id, $openid, $unionid);
            if (true === $res) {
                $user->openid  = $openid;
                $user->unionid = $unionid;
            }
        }
        if ((!empty($unionid) && !empty($user->unionid) && $unionid!==$user->unionid) || (empty($user->unionid) && !empty($user->openid) && !empty($openid) && $openid!==$user->openid)){
            throw new OilcardException("该帐号已绑定其他微信帐号，请先解绑后再登录");
        }
        return $this->goUserLogin($user,3);

    }

    /**
     * 验证码登陆
     * @param $mobile
     * @param $code
     * @param $openid
     * @param $unionid
     * @param $inviteId
     * @return string|null
     * @throws OilcardException
     */
    public function smsLogin($mobile,$code,$openid,$unionid,$inviteId)
    {
        $verify = Sms::verify($mobile, $code, Sms::LOGIN_TEMPLATE);
        if (false === $verify) {
            throw new OilcardException('验证码错误');
        }
        $user = (new User())->where('mobile',$mobile)->first();
        if (!$user){
            $user = $this->goUserRegister($mobile,$openid,$unionid,$inviteId);
        }
        if (empty($user->openid) && empty($user->unionid) && (!empty($openid) || !empty($unionid))) {
            $res = $this->bindWechat($user->id, $openid, $unionid);
            if (true === $res) {
                $user->openid  = $openid;
                $user->unionid = $unionid;
            }
        }
        if ((!empty($unionid) && !empty($user->unionid) && $unionid!==$user->unionid) || (empty($user->unionid) && !empty($user->openid) && !empty($openid) && $openid!==$user->openid)){
            throw new OilcardException("该帐号已绑定其他微信帐号，请先解绑后再登录");
        }
        return $this->goUserLogin($user,2);
    }

    /**
     * 用户登录
     * @param $user
     * @param $way
     * @return string|null
     * @throws OilcardException
     */
    public function goUserLogin($user,$way)
    {
        if (isset($user->user_status) && 2 === (int) $user->user_status) {
            throw new OilcardException('该账户已被禁用，请联系客服');
        }

        if (isset($user->user_status) && 3 === (int) $user->user_status) {
            throw new OilcardException('该账户已锁住，请联系客服或稍后再尝试');
        }
        $this->writeLoginLog($user,$way,$user->id);
        $user->last_ip = $this->ip;
        $user->last_time = Carbon::now();
        $user->save();

        $token = sha1(sha1($user->id) . mt_rand(1000, 9999));
        if (in_array($this->platform,['ios','android'])){
            $ttl = 86400 * 30;
        }else{
            $ttl = 86400;
        }
        Redis::connection('default')->setex($token,$ttl,json_encode($user));
        return $token;
    }

    /**
     * 用户注册
     * @param $mobile
     * @param $openid
     * @param $unionid
     * @param $inviteId
     * @return User
     */
    public function goUserRegister($mobile,$openid,$unionid,$inviteId)
    {
        $user = new User();
        $user->mobile = $mobile;
        $user->openid = $openid;
        $user->unionid = $unionid;
        $user->last_ip = $this->ip;
        $user->last_time = Carbon::now();
        $user->login_count = 1;
        $user->invite_id = $inviteId;
        $user->app_platform = $this->platform;
        $user->app_channel = $this->channel;
        $user->app_version = $this->version;
        $user->imei = $this->imei;
        $user->app_name = $this->appName;
        $user->save();
        return $user;
    }

    /**
     * 记录登陆日志
     * @param $user
     * @param $way
     * @param $userId
     */
    public function writeLoginLog($user,$way,$userId)
    {
        $loginLog = new UserLoginLog();
        $loginLog->user_id = $userId;
        $loginLog->login_way = $way;
        $loginLog->app_platform = $this->platform??'';
        $loginLog->app_version = $this->version??'';
        $loginLog->app_name = $this->appName??'';
        $loginLog->login_ip = $this->ip;
        $loginLog->save();

        $user->login_count = $user->login_count+1;
        $user->save();
    }

    /**
     * 发送验证码
     * @param $mobile
     * @return array
     * @throws OilcardException
     * @throws \AlibabaCloud\Client\Exception\ClientException
     * @throws \AlibabaCloud\Client\Exception\ServerException
     */
    public function sendSms($mobile)
    {
        return (new Sms())->sendVerifyCode($mobile,Sms::LOGIN_TEMPLATE,$this->ip,'login');
    }

    /**
     * 获取微信access_token
     * @param $code
     * @return mixed
     * @throws OilcardException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getAccessToken($code)
    {
        $config = config('wechat.public');
        $client = new Client();
        $hostUrl = $config['host'].'?appid='.$config['appId'].'&secret='.$config['appSecret'].'&code='.$code.'&grant_type=authorization_code';
        $response = $client->request("GET",$hostUrl,["verify"=>false]);
        if($response->getStatusCode()!=200) {
            throw new OilcardException("获取ACCESS_TOKEN失败");
        }
        $body = $response->getBody()->getContents();
        return json_decode($body,true);
    }

    /**
     * 微信登陆
     * @param $openid
     * @param $unionid
     * @return string|null
     * @throws OilcardException
     */
    public function weixinLogin($openid,$unionid=null)
    {
        $user = $this->getWxUserInfo($openid,$unionid);
        if ($user){
            return $this->goUserLogin($user,1);
        }
        return null;
    }

    /**
     * 根据微信信息获取用户信息
     * @param $openid
     * @param null $unionid
     * @return mixed
     */
    public function getWxUserInfo($openid,$unionid=null)
    {
        if (!empty($unionid)){
            $user = (new User())->where(function ($query)use($unionid){
                $query->where("unionid",$unionid)->where("is_deleted",0)->where("user_status",1);
            })->first();
        }else{
            $user = (new User())->where(function ($query)use($openid){
                $query->where("openid",$openid)->where("is_deleted",0)->where("user_status",1);
            })->first();
        }
        return $user;
    }

    /**
     * 绑定电话
     * @param $mobile
     * @param $smsCode
     * @param $openid
     * @param null $unionid
     * @param null $nickname
     * @param null $avatar
     * @param int $inviteId
     * @return string|null
     * @throws OilcardException
     */
    public function bindMobile($mobile, $smsCode, $openid, $unionid=null, $nickname=null, $avatar=null,$inviteId=0)
    {
        if (false === Sms::verify($mobile,$smsCode,Sms::LOGIN_TEMPLATE)){
            throw new OilcardException("验证码错误");
        }
        $mobileUser = (new User())->where("mobile",$mobile)->where("is_deleted",0)->first();
        if ($mobileUser){
            $this->bindWechat($mobileUser->id,$openid,$unionid);
            $mobileUser->openid  = $openid;
            $mobileUser->unionid = $unionid;
            return $this->goUserLogin($mobileUser, 1);
        }
        $user = $this->getWxUserInfo($openid,$unionid);
        if (!empty($user) && !empty($user['mobile'])) {
            if ($user->mobile === $mobile) {
                return $this->goUserLogin($user, 1);
            } else {
                throw new OilcardException('该帐号已绑定其他手机号，请直接登录');
            }
        }
        if (!$user){
            $user = new User();
            $user->mobile = $mobile;
            $user->avatar = $avatar;
            $user->nickname = $nickname;
            $user->openid = $openid;
            $user->unionid = $unionid;
            $user->last_ip = $this->ip;
            $user->last_time = Carbon::now();
            $user->login_count = 1;
            $user->invite_id = $inviteId;
            $user->app_platform = $this->platform;
            $user->app_channel = $this->channel;
            $user->app_version = $this->version;
            $user->imei = $this->imei;
            $user->app_name = $this->appName;
            $user->save();
            return $this->goUserLogin($user,1);
        }else{
            $user->mobile = $mobile;
            $user->save();
            return $this->goUserLogin($user,1);
        }
    }

    /**
     * 绑定微信
     *
     * @author yls
     * @param int    $uid
     * @param string $openid
     * @param string $unionid
     * @return bool
     * @throws OilcardException
     */
    public function bindWechat(int $uid, string $openid, string $unionid)
    {
        $user = (new User())->find($uid);
        if (!empty($user->openid) || !empty($user->unionid)) {
            throw new OilcardException('该手机号已绑定微信，请解绑后再进行绑定');
        } else {
            $user->openid = $openid;
            $user->unionid = $unionid;
            $user->save();
            return true;
        }
    }
}